#include <iostream>
#include <variant>
#include <string>
#include <vector>
#include <iomanip>

// 为variant定义访问器
struct PrintVisitor {
    void operator()(int value) const {
        std::cout << "  整数: " << value << '\n';
    }
    
    void operator()(double value) const {
        std::cout << "  浮点数: " << std::fixed << std::setprecision(2) << value << '\n';
    }
    
    void operator()(const std::string& value) const {
        std::cout << "  字符串: \"" << value << "\"\n";
    }
};

// 返回类型随输入类型变化的访问器
// 注意：std::visit要求所有重载返回相同类型，这里统一返回std::string
struct TransformVisitor {
    std::string operator()(int value) const {
        return std::to_string(value * 2);
    }
    
    std::string operator()(double value) const {
        return std::to_string(value * 2.5);
    }
    
    std::string operator()(const std::string& value) const {
        return value + value;  // 字符串重复
    }
};

// 递归访问器，处理递归变体
struct RecursiveVisitor {
    void operator()(int value) const {
        std::cout << value << " ";
    }
    
    void operator()(double value) const {
        std::cout << std::fixed << std::setprecision(1) << value << " ";
    }
    
    void operator()(const std::string& value) const {
        std::cout << "\"" << value << "\" ";
    }
    
    void operator()(const std::vector<std::variant<int, double, std::string>>& vec) const {
        std::cout << "[ ";
        for (const auto& v : vec) {
            std::visit(*this, v);
        }
        std::cout << "] ";
    }
};

void demonstrate_variant() {
    std::cout << "  std::variant演示:\n\n";
    
    // 1. 基本用法
    std::cout << "  基本用法:\n";
    
    // 创建多种类型的variant
    std::variant<int, double, std::string> v1 = 42;
    std::variant<int, double, std::string> v2 = 3.14;
    std::variant<int, double, std::string> v3 = "你好，世界";
    
    // 检查当前保存的类型
    std::cout << "  v1的索引: " << v1.index() << '\n';
    std::cout << "  v2的索引: " << v2.index() << '\n';
    std::cout << "  v3的索引: " << v3.index() << '\n';
    
    // 使用get<T>访问特定类型
    std::cout << "  v1的值: " << std::get<int>(v1) << '\n';
    std::cout << "  v2的值: " << std::get<double>(v2) << '\n';
    std::cout << "  v3的值: " << std::get<std::string>(v3) << '\n';
    
    // 使用get<index>访问
    std::cout << "  使用索引访问v3: " << std::get<2>(v3) << '\n';
    
    // 2. 修改variant的值
    std::cout << "\n  修改variant:\n";
    v1 = "现在是字符串";
    v2 = 100;
    
    std::cout << "  修改后v1的类型索引: " << v1.index() << '\n';
    std::cout << "  修改后v2的类型索引: " << v2.index() << '\n';
    
    // 使用get_if安全地访问值
    if (const auto ptr = std::get_if<std::string>(&v1)) {
        std::cout << "  v1是字符串: " << *ptr << '\n';
    }
    
    if (const auto ptr = std::get_if<int>(&v2)) {
        std::cout << "  v2是整数: " << *ptr << '\n';
    }
    
    // 3. 使用访问者模式
    std::cout << "\n  使用访问者模式:\n";
    std::visit(PrintVisitor{}, v1);
    std::visit(PrintVisitor{}, v2);
    std::visit(PrintVisitor{}, v3);
    
    // 使用泛型lambda作为访问器
    std::cout << "\n  使用lambda访问器:\n";
    auto print_visitor = [](const auto& val) {
        using T = std::decay_t<decltype(val)>;
        if constexpr (std::is_same_v<T, int>) {
            std::cout << "  Lambda访问整数: " << val << '\n';
        } else if constexpr (std::is_same_v<T, double>) {
            std::cout << "  Lambda访问浮点数: " << val << '\n';
        } else if constexpr (std::is_same_v<T, std::string>) {
            std::cout << "  Lambda访问字符串: " << val << '\n';
        }
    };
    
    std::visit(print_visitor, v1);
    std::visit(print_visitor, v2);
    std::visit(print_visitor, v3);
    
    // 4. 带返回值的访问器
    std::cout << "\n  变换访问器:\n";
    auto result1 = std::visit(TransformVisitor{}, v1);
    auto result2 = std::visit(TransformVisitor{}, v2);
    auto result3 = std::visit(TransformVisitor{}, v3);
    
    std::cout << "  v1变换结果: " << result1 << '\n';
    std::cout << "  v2变换结果: " << result2 << '\n';
    std::cout << "  v3变换结果: " << result3 << '\n';
    
    // 5. variant的容器
    std::cout << "\n  variant容器:\n";
    std::vector<std::variant<int, double, std::string>> vec = {
        42, 3.14, "variant", 987, 6.28
    };
    
    std::cout << "  容器内容: ";
    for (const auto& item : vec) {
        std::visit(PrintVisitor{}, item);
    }
    
    // 6. 嵌套variant
    std::cout << "\n  嵌套variant:\n";
    using recursive_variant = std::variant<
        int, double, std::string,
        std::vector<std::variant<int, double, std::string>>
    >;
    
    std::vector<std::variant<int, double, std::string>> inner_vec = {1, 2.5, "三"};
    recursive_variant nested = inner_vec;
    
    std::cout << "  嵌套结构: ";
    std::visit(RecursiveVisitor{}, nested);
    std::cout << '\n';
} 